package org.tong.aspect;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.aop.support.JdkRegexpMethodPointcut;
import org.springframework.aop.support.annotation.AnnotationMatchingPointcut;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.tong.jpa.entities.Student;

import java.lang.annotation.*;

/**
 * @author
 * @date 2022-09-01 10:36
 */
@Configuration
public class AspectCfg {

    @Bean
    public Advisor testAdvisor() {
        AspectJExpressionPointcutAdvisor advisor = new AspectJExpressionPointcutAdvisor();
        advisor.setAdvice(new MethodInterceptor() {
            @Override
            public Object invoke(MethodInvocation methodInvocation) throws Throwable {
                System.out.println("自动注入 Advisor before");
                Object result = methodInvocation.proceed();
                System.out.println("自动注入 Advisor after");
                return result;
            }
        });
        advisor.setExpression("execution(public * org.tong..*.*Controller.*(..))");
        advisor.setOrder(2);
        return advisor;
    }


    @Bean
    public Advisor testAnnoAdvisor() {
        DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor();
        advisor.setAdvice(new MethodInterceptor() {
            @Override
            public Object invoke(MethodInvocation invocation) throws Throwable {
                System.out.println("注解 Advisor before");
                Object result = invocation.proceed();
                System.out.println("注解 Advisor after");
                return result;
            }
        });
        advisor.setPointcut(AnnotationMatchingPointcut.forMethodAnnotation(VistLog.class));
        advisor.setOrder(1);
        return advisor;
    }


    @Target({ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface VistLog {

    }

    public static void main(String[] args) {
        Student student = new Student(1L, "xiaoming", 1);


        // 创建切面对象
        DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor();
        advisor.setAdvice(new MethodInterceptor() {
            @Override
            public Object invoke(MethodInvocation invocation) throws Throwable {
                System.out.println("proxyFactory before");
                Object result = invocation.proceed();
                System.out.println("proxyFactory after");
                return result;
            }
        });
        JdkRegexpMethodPointcut pointCut = new JdkRegexpMethodPointcut();
        pointCut.setPattern(".*get.*");
        advisor.setPointcut(pointCut);
        // 执行代理
        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.addAdvisor(advisor);
        proxyFactory.setTarget(student);
        // 获取代理对象
        Student studentProxy = (Student) proxyFactory.getProxy();
        System.out.println(studentProxy.getName());
    }
}
